package com.yimo.chromedriver;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xiaoju.automarket.knife.util.JsonUtil;
import com.xiaoju.automarket.knife.util.StringUtil;
import com.yimo.common.exception.BaseErrors;
import com.yimo.common.exception.BusinessException;
import com.yimo.common.module.crawler.ProductFor1688;
import com.yimo.common.module.crawler.SkuFor1688;
import com.yimo.common.module.crawler.SkuMapInfo;
import com.yimo.common.module.crawler.SkuProp;
import com.yimo.common.response.BaseResponse;
import com.yimo.common.service.ProductApiService;
import com.yimo.common.vo.IdVo;
import com.yimo.imgtransfer.Product;
import lombok.Data;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import sun.awt.OSInfo;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;

/**
 * create by jsm on 2018/10/31
 */
@Data
@Component
public class Alibaba extends Crawler {
    @Resource
    private ProductApiService productApiService;
    private Long platformId;
    private Long cagtegoryId;
    private Long shopId;
    ThreadPoolExecutor excuter = new ThreadPoolExecutor(10, 20, 1000, TimeUnit.MICROSECONDS,
            new LinkedBlockingDeque <>(10), new ThreadPoolExecutor.CallerRunsPolicy());

    public void climb() throws InterruptedException {
        if (getUrl() == null) {
            throw new BusinessException(BaseErrors.SERVER_ERROR.setEmArgs("url can not be null").setArgs("url can not be null"));
        }
        ChromeDriver chromeDriver = open();
        int pageCount = Integer.parseInt(chromeDriver.findElement(By.className("page-count")).getText());
        String currentUrl = chromeDriver.getCurrentUrl();
        chromeDriver.quit();
        for (int i = 1; i < 1 + 1; i++) {
            setUrl(currentUrl + "&pageNum=" + i);
            ChromeDriver open = open();
            new Thread(() -> crawlerCurrentPage(open)).start();
        }


    }

    private void redirectNextPage(ChromeDriver chromeDriver) throws InterruptedException {
        chromeDriver.findElement(By.className("pagination")).findElement(By.className("next")).click();
        Thread.sleep(2000L);
    }

    private boolean hasNextPage(ChromeDriver chromeDriver) {
        int current = Integer.parseInt(chromeDriver.findElement(By.className("current")).getText());
        int pageCount = Integer.parseInt(chromeDriver.findElement(By.className("page-count")).getText());
        return current < pageCount;
    }

    private void crawlerCurrentPage(ChromeDriver chromeDriver) {

        WebElement productsElement = chromeDriver.findElement(By.className("common-column-230"));
        List <WebElement> products = productsElement.findElements(By.className("offer-list-row-offer"));
        if (products != null && products.size() > 0) {
            for (WebElement product : products) {
                try {
                    crawlerCurrentProduct(chromeDriver, product, getShopNameByShopPage(chromeDriver));
                } catch (Exception e) {
                    e.printStackTrace();
                    continue;
                }

            }
            switchTo(chromeDriver, 0);
        }
        chromeDriver.quit();
        return;
    }

    private String getShopNameByShopPage(ChromeDriver chromeDriver) {
        return chromeDriver.getCurrentUrl().substring(getUrl().indexOf("//") + 2, getUrl().indexOf("."));
    }

    private void openNewWindow(ChromeDriver chromeDriver) {
        chromeDriver.executeScript("window.open()");
    }

    private void switchTo(ChromeDriver chromeDriver, int window) {
        ArrayList <String> tabs = new ArrayList <>(chromeDriver.getWindowHandles());
        chromeDriver.switchTo().window(tabs.get(window));
    }

    private void crawlerCurrentProduct(ChromeDriver chromeDriver, WebElement product, String shopName) {

        WebElement image = product.findElement(By.className("image"));
        WebElement a = image.findElement(By.tagName("a"));
        String url = a.getAttribute("href");
        openNewWindow(chromeDriver);
        switchTo(chromeDriver, 1);
        try {
            try {
                chromeDriver.get(url);
            } catch (WebDriverException w) {
                chromeDriver.executeScript("window.stop()");
            }
            ProductFor1688 productFor1688 = buildProduct(chromeDriver, shopName);
            BaseResponse <IdVo> idVoBaseResponse = productApiService.save103(productFor1688);
            System.out.println("product response :" + JsonUtil.toJson(idVoBaseResponse));
        } catch (Exception e) {
            e.printStackTrace();
            return;
        } finally {
            chromeDriver.close();
            switchTo(chromeDriver, 0);
        }
    }

//    @Data
//    class UploadProductJob implements Runnable {
//        private ProductFor1688 product;
//
//        @Override
//        public void run() {
//
//        }
//    }

    private ProductFor1688 buildProduct(ChromeDriver chromeDriver, String shopName) {
        ProductFor1688 productFor1688 = new ProductFor1688();
        productFor1688.setProductId(getProductId(chromeDriver));
        productFor1688.setMainImages(getMainImage(chromeDriver));
        productFor1688.setShopName(shopName);
        if (shopName == null) {
            productFor1688.setShopName(getShopNameByProductPage(chromeDriver));
        }
        productFor1688.setSubject(getSubject(chromeDriver));
        productFor1688.setPrice(getProductPrice(chromeDriver));
        setSkuMapAndSkuProps(chromeDriver, productFor1688);
        if (productFor1688.getSkuMap() == null || productFor1688.getSkuProps() == null) {
            productFor1688.setStock(getProductStock(chromeDriver));
        }
        productFor1688.setShopId(getShopId());
        productFor1688.setPlatformId(getPlatformId());
        productFor1688.setCategoryId(getCagtegoryId());
        productFor1688.setDetailHtml(getProductDetailHtml(chromeDriver));
        return productFor1688;
    }

    private String getShopNameByProductPage(ChromeDriver chromeDriver) {
        String href = chromeDriver.findElement(By.className("base-info")).findElement(By.tagName("a")).getAttribute("href");
        return href.substring(href.indexOf("//") + 2, href.indexOf("."));
    }

    private String getProductDetailHtml(ChromeDriver chromeDriver) {
        chromeDriver.executeScript("window.scrollTo(0, document.body.scrollHeight)");
        try {
            Thread.sleep(1500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String detailHtml = chromeDriver.findElement(By.className("desc-lazyload-container")).getAttribute("outerHTML");
        return detailHtml;
    }

    private Integer getProductStock(ChromeDriver chromeDriver) {
        String dataModConfig = chromeDriver.findElement(By.className("mod-detail-purchasing")).getAttribute("data-mod-config");
        Integer max = JSONObject.parseObject(dataModConfig).getInteger("max");
        return max;
    }

    private BigDecimal getProductPrice(ChromeDriver chromeDriver) {
        Object iDetailConfig = chromeDriver.executeScript("return iDetailConfig");
        System.out.println("idetailConfig :" + iDetailConfig.toString());
        JSONObject jsonObject = JSON.parseObject(JsonUtil.toJson(iDetailConfig));
        return jsonObject.getBigDecimal("refPrice");
    }

    private void setSkuMapAndSkuProps(ChromeDriver chromeDriver, ProductFor1688 productFor1688) {
        Object iDetailData = chromeDriver.executeScript("return iDetailData");
        System.out.println("iDetailData :" + JsonUtil.toJson(iDetailData));
        if (iDetailData != null && !StringUtil.isEmpty(iDetailData.toString())) {
            JSONObject jsonObject = JSON.parseObject(JsonUtil.toJson(iDetailData));
            JSONObject skuJsonObject = jsonObject.getJSONObject("sku");
            if (skuJsonObject == null) {
                return;
            }
            JSONArray skuProps = skuJsonObject.getJSONArray("skuProps");
            List <SkuProp> skuPropList = new ArrayList <>();
            for (int i = 0; i < skuProps.size(); i++) {
                SkuProp skuProp = JsonUtil.fromJson(skuProps.getJSONObject(i).toJSONString(), SkuProp.class);
                skuPropList.add(skuProp);
            }
            JSONObject skuMap = skuJsonObject.getJSONObject("skuMap");
            Map <String, SkuMapInfo> skuMapInfoMap = new HashMap <>();
            Set <String> keySet = skuMap.keySet();
            Iterator <String> iterator = keySet.iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                skuMapInfoMap.put(key, JsonUtil.fromJson(skuMap.getJSONObject(key).toJSONString(), SkuMapInfo.class));
            }
            productFor1688.setSkuMap(skuMapInfoMap);
            productFor1688.setSkuProps(skuPropList);
        }
        return;
    }

    private String getSubject(ChromeDriver chromeDriver) {
        WebElement title = chromeDriver.findElement(By.tagName("h1"));
        String text = title.getText();
        return text;
    }

    private List <String> getMainImage(ChromeDriver chromeDriver) {
        List <String> mainImages = new ArrayList <>();
        List <WebElement> tabs = chromeDriver.findElements(By.className("tab-trigger"));
        if (tabs != null && tabs.size() > 0) {
            for (int i = 0; i < tabs.size(); i++) {
                if (i > 0 && i % 5 == 0) {
                    WebElement element;
                    try {
                        element = chromeDriver.findElement(By.cssSelector("a.paging.next"));
                        element.click();
                    } catch (Exception e) {
                        element = chromeDriver.findElement(By.cssSelector("a.preview-arrow-btn.next"));
                        element.click();
                    }
                    try {
                        Thread.sleep(100L);
                    } catch (Exception e) {
                        continue;
                    }

                }
                System.out.println("i=" + i);
                tabs.get(i).click();
                mainImages.add(change(chromeDriver));
            }
        }
        System.out.println("mainImages:" + JsonUtil.toJson(mainImages));
        return mainImages;
    }

    private String change(ChromeDriver chromeDriver) {
        try {
            Thread.sleep(400L);
        } catch (InterruptedException e) {
            return "";
        }
        WebElement pane = chromeDriver.findElement(By.className("tab-pane"));
        String src = pane.findElement(By.tagName("img")).getAttribute("src");
        System.out.println("change main image src" + src);
        return src;
    }

    private Long getProductId(ChromeDriver chromeDriver) {
        System.out.println("get ProductId cheomeDriver currentUrl:" + chromeDriver.getCurrentUrl());
        String currentUrl = chromeDriver.getCurrentUrl();
        return Long.parseLong(currentUrl.substring(currentUrl.indexOf("offer/") + 6, currentUrl.indexOf(".html")));
    }


    private ChromeDriver climbSingleDriver = null;

    public ChromeDriver climbSingle() {
        if (climbSingleDriver == null) {
            climbSingleDriver = open();
        } else {
            climbSingleDriver.get(getUrl());
        }

        ProductFor1688 productFor1688 = buildProduct(climbSingleDriver, null);
        BaseResponse <IdVo> idVoBaseResponse = productApiService.save103(productFor1688);

        return climbSingleDriver;
    }

//public static void main(String[] args) throws InterruptedException {
//    Alibaba alibaba = new Alibaba();
//    alibaba.setDriverPath("/usr/local/bin/chromedriver");
//    alibaba.setUrl("https://shop1489424685141.1688.com/page/offerlist.htm?priceStart=0.8&priceEnd=1.6&sortType=wangpu_score&keywords=&activityOfferFilter=&sellerRecommendFilter=false&videoFilter=false&sampleFilter=false&mixFilter=false&tradenumFilter=false&feature=&tags=&brandCountryId=&brandId=&quantityBegin=");
//    alibaba.climb();
//}


    public static void main(String[] args) {
        LinkedBlockingQueue <String> imgQueue = new LinkedBlockingQueue(1000);
        System.out.println(imgQueue.size());
    }
}
